#ifndef APR_H_
#define ARP_H_

#include "hw.h"
#include <assert.h>
#include <stdbool.h>

#define ETH_P_ARP23 0x2023
#define UNIX_PATH_MAX 256
#define ARP_ID 0x2123
#define ARPOP_REQUEST 1
#define ARPOP_REPLY 2
#define ARP_SUNPATH "/tmp/grp23.arp23"
#define CLI_SUNPATH_TMPL "/tmp/grp23.XXXXXX"

extern struct hwa_info *hwlist, *hweth0;
extern int ifcount;
extern int *if_idx;
extern int *pfd;
extern struct sockaddr_ll *pfa;

typedef struct {
	unsigned char addr[ETH_ALEN];
} eth_addr;

typedef struct {
	int             ifindex;	/* Interface number */
	unsigned short  hatype;		/* Hardware type */
	unsigned char   halen;		/* Length of address */
	unsigned char   hwaddr[8];	/* Physical layer address */
} arp_hwaddr;

/* ARP packet */
typedef struct {
	unsigned short 	arpid;
  	unsigned short 	htype;
  	unsigned short 	ptype;
  	unsigned char  	hlen;
  	unsigned char  	plen;
  	unsigned short 	op;
  	eth_addr  	sender_mac;
  	unsigned char  	sender_ip[INET_ADDRSTRLEN];
  	eth_addr  	target_mac;
  	unsigned char  	target_ip[INET_ADDRSTRLEN];
} arp_pkt;

/* Ethernet ARP packet */
typedef struct {
  	struct ethhdr 	ehdr;
	arp_pkt 	apkt;
} eth_pkt;

typedef struct {
	unsigned char 	ip[INET_ADDRSTRLEN];
	eth_addr 	hwaddr;
	int    		ifindex;	/* Interface number */
	unsigned short  hatype;		/* Hardware type */
	int 		confd;
	bool 		valid;
} arp_entry;

typedef struct arp_list {
	arp_entry aentry;
	struct arp_list *next;
} arp_list;

extern arp_list *arp_head;

void print_mac(unsigned char *mac); 
void insert_arp_node(arp_list **head, arp_list *node);
void create_arp_node(arp_list **head, arp_entry *aentry);
void update_arp_node(arp_list **head, arp_list *node, arp_pkt *apkt, int ifidx);
void free_arp_node(struct arp_list *node);
arp_list *del_arp_node(struct arp_list **head, char *ipaddr, int confd);
arp_list *find_arp_node(arp_list *head, char *ipaddr);
void insert_begin(struct hwa_info *node);
struct hwa_info* find_hw_node(char *ipaddr); 
int areq (struct in_addr *ipaddr, socklen_t sockaddrlen, arp_hwaddr *addr);

#endif
